// EditorView.java
package exercise.jslide.jslide.view;

import exercise.jslide.jslide.model.image.ImageElement;
import exercise.jslide.jslide.model.shapes.Shape;
import exercise.jslide.jslide.model.text.TextBox;
import exercise.jslide.jslide.view.tools.SelectTool;
import javafx.scene.layout.StackPane;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.geometry.Point2D;
import exercise.jslide.jslide.model.Slide;
import exercise.jslide.jslide.model.SlideElement;
import exercise.jslide.jslide.app.AppContext;
import exercise.jslide.jslide.view.tools.Tool;

public class EditorView extends StackPane {
    private Canvas canvas;
    private GraphicsContext gc;
    private AppContext appContext;

    private SlideElement selectedElement;
    private Point2D lastMousePosition;
    private boolean isDragging;
    private Tool currentTool; // 当前选中的工具

    public EditorView() {
        appContext = AppContext.getInstance();
        initializeComponents();
        setupCanvas();
        setupEventHandlers();
        this.setAlignment(javafx.geometry.Pos.TOP_LEFT);
    }

    private void initializeComponents() {
        canvas = new Canvas(800, 600);
        gc = canvas.getGraphicsContext2D();
        getChildren().add(canvas);

        // 设置 Canvas 的最小和最大尺寸
        canvas.minWidth(400);
        canvas.minHeight(300);
        canvas.maxWidth(1600);
        canvas.maxHeight(1200);
    }

    private void setupCanvas() {
        canvas.widthProperty().bind(widthProperty());
        canvas.heightProperty().bind(heightProperty());

        canvas.widthProperty().addListener((obs, oldVal, newVal) -> redraw());
        canvas.heightProperty().addListener((obs, oldVal, newVal) -> redraw());
    }

    public void setCurrentTool(Tool tool) {
        if(currentTool==null||tool == null||currentTool.getClass()!=tool.getClass()) {
            if (currentTool != null) {
                currentTool.deactivate();
            }
            currentTool = tool;
            if (currentTool != null) {
                currentTool.activate();
            }
        }else{
            if (currentTool.getClass() == SelectTool.class){
                SelectTool selectTool = (SelectTool) currentTool;
                if(selectTool.getSelectedElement() != selectedElement){
                    currentTool.deactivate();
                    currentTool = tool;
                    currentTool.activate();
                }else{
                    selectTool.setStartX(lastMousePosition.getX());
                    selectTool.setStartY(lastMousePosition.getY());
                }
            }
        }
    }

    public Tool getCurrentTool() {
        return currentTool;
    }

    private void setupEventHandlers() {
        canvas.setOnMousePressed(event -> {
            if (currentTool != null&&currentTool.getClass() != SelectTool.class) {
                // 如果有活动的工具，使用工具处理事件
                currentTool.handleMousePressed(event.getX(), event.getY());
            } else {
                // 否则使用默认的选择行为
                handleSelectionMousePressed(event);
            }
        });

        canvas.setOnMouseDragged(event -> {
            if (currentTool != null) {
                currentTool.handleMouseDragged(event.getX(), event.getY());
            } else {
                handleSelectionMouseDragged(event);
            }
        });

        canvas.setOnMouseReleased(event -> {
            if (currentTool != null) {
                currentTool.handleMouseReleased(event.getX(), event.getY());
                // 在工具完成操作后
//                 setCurrentTool(null);
            } else {
                handleSelectionMouseReleased(event);
            }
        });

        canvas.setOnMouseClicked(event -> {

            if (event.getClickCount() == 2) {
                handleDoubleClick(event);
            }
        });
    }

    private void handleDoubleClick(MouseEvent event) {
        // 双击时，查找元素并进入编辑状态
        Slide currentSlide = appContext.getCurrentPresentation().getCurrentSlide();
        if (currentSlide != null) {
            for (SlideElement element : currentSlide.getElements().reversed()) {
                if (element.contains(new Point2D(event.getX(), event.getY()))) {
                    // 进入编辑状态
                    element.setEditing(true);
                    redraw();

                    setCurrentTool(new SelectTool(this, element,event.getX(), event.getY()));
                    break;
                }
            }
        }
    }

    // 重命名原来的鼠标事件处理方法，使其专门处理选择功能
    private void handleSelectionMousePressed(MouseEvent event) {
        lastMousePosition = new Point2D(event.getX(), event.getY());

        Slide currentSlide = appContext.getCurrentPresentation().getCurrentSlide();
        if (currentSlide != null) {
            selectedElement = null;
            for (SlideElement element : currentSlide.getElements().reversed()) {
                if (element.contains(lastMousePosition)) {
                    selectedElement = element;
                    SelectTool selectTool = new SelectTool(this, element,event.getX(), event.getY());
                    selectTool.setStartX(event.getX());
                    selectTool.setStartY(event.getY());
                    selectTool.setInitialX(element.getX());
                    selectTool.setInitialY(element.getY());
                    setCurrentTool(selectTool);

                    if (selectedElement != null) {
                        if (selectedElement.getClass() == ImageElement.class){
                            ImageElement imageElement = (ImageElement) selectedElement;
                            imageElement.setEdgePoint(new Point2D(event.getX(), event.getY()));
                        } else if (selectedElement.getClass().getSuperclass() == Shape.class){
                            Shape shape = (Shape) selectedElement;
                            shape.setEdgePoint(new Point2D(event.getX(), event.getY()));
                        } else if (selectedElement.getClass() == TextBox.class){
                            TextBox textBox = (TextBox) selectedElement;
                            textBox.setEdgePoint(new Point2D(event.getX(), event.getY()));
                        }
                    }
                    break;
                }else{
                    setCurrentTool(null);
                }
            }
            updateSelection();
        }
    }

    private void handleSelectionMouseDragged(MouseEvent event) {
        if (isDragging && selectedElement != null) {
            double deltaX = event.getX() - lastMousePosition.getX();
            double deltaY = event.getY() - lastMousePosition.getY();

            selectedElement.move(deltaX, deltaY);
            lastMousePosition = new Point2D(event.getX(), event.getY());

            redraw();
        }
    }

    private void handleSelectionMouseReleased(MouseEvent event) {
        if (isDragging) {
            isDragging = false;
            // TODO: 记录移动命令用于撤销/重做
        }
    }


    private void updateSelection() {
        Slide currentSlide = appContext.getCurrentPresentation().getCurrentSlide();
        if (currentSlide != null) {
            for (SlideElement element : currentSlide.getElements()) {
                element.setSelected(element == selectedElement);
            }
            redraw();
        }
    }

    public void redraw() {
        // 清除画布
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

        // 绘制当前幻灯片
        Slide currentSlide = appContext.getCurrentPresentation().getCurrentSlide();

        if (currentSlide != null) {
            // 绘制背景
            gc.setFill(javafx.scene.paint.Color.WHITE);
            gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

            // 绘制所有元素
            for (SlideElement element : currentSlide.getElements()) {

                element.draw(gc);

                // 如果元素被选中，绘制选中框
                if (element.isSelected()) {
                    drawSelectionFrame(element);
                }
            }
        }
    }

    public void singleredraw() {
        //需要当前的元素
        Slide currentSlide = appContext.getCurrentPresentation().getCurrentSlide();
        int elementnum = 0;
        for(SlideElement element : currentSlide.getElements())
        {
            elementnum++;
        }
        int eleindex = 0;
        for(SlideElement element : currentSlide.getElements())
        {
            eleindex++;
            if(eleindex == elementnum)
            {
                element.draw(gc);
            }
            else continue;
        }
    }


    private void drawSelectionFrame(SlideElement element) {
        gc.setStroke(javafx.scene.paint.Color.BLUE);
        gc.setLineDashes(5);
        gc.strokeRect(
                element.getX() - 2,
                element.getY() - 2,
                element.getWidth() + 4,
                element.getHeight() + 4
        );
        gc.setLineDashes(null);

        // 绘制调整大小的控制点
        drawResizeHandles(element);
    }

    private void drawResizeHandles(SlideElement element) {
        double[] handlePositions = {
                element.getX(), element.getY(),                              // 左上
                element.getX() + element.getWidth()/2, element.getY(),      // 上中
                element.getX() + element.getWidth(), element.getY(),        // 右上
                element.getX() + element.getWidth(), element.getY() + element.getHeight()/2,  // 右中
                element.getX() + element.getWidth(), element.getY() + element.getHeight(),    // 右下
                element.getX() + element.getWidth()/2, element.getY() + element.getHeight(),  // 下中
                element.getX(), element.getY() + element.getHeight(),       // 左下
                element.getX(), element.getY() + element.getHeight()/2      // 左中
        };

        gc.setFill(javafx.scene.paint.Color.WHITE);
        gc.setStroke(javafx.scene.paint.Color.BLUE);

        for (int i = 0; i < handlePositions.length; i += 2) {
            gc.fillRect(handlePositions[i] - 4, handlePositions[i + 1] - 4, 8, 8);
            gc.strokeRect(handlePositions[i] - 4, handlePositions[i + 1] - 4, 8, 8);
        }
    }

    public GraphicsContext getGraphicsContext() {
        return gc;
    }

    public void clearSelection() {
        if(selectedElement != null) {
            selectedElement.setSelected(false);
            selectedElement.setEditing(false);
            selectedElement = null;
            redraw();
        }
//        isDragging = false;
        updateSelection();
    }

    public SlideElement getSelectedElement() {
        return selectedElement;
    }

    public void copy() {
        if (currentTool != null&&currentTool.getClass() == SelectTool.class) {
            SelectTool selectTool = (SelectTool) currentTool;
            SlideElement selectedElement = selectTool.getSelectedElement();
            if (selectedElement != null) {
                appContext.setClipboard(selectedElement);
            }
        }
    }

    public void cut() {
        if (currentTool != null&&currentTool.getClass() == SelectTool.class) {
            SelectTool selectTool = (SelectTool) currentTool;
            SlideElement selectedElement = selectTool.getSelectedElement();
            if (selectedElement != null) {
                appContext.setClipboard(selectedElement);
                appContext.getCurrentPresentation().getCurrentSlide().removeElement(selectedElement);
                if (selectedElement != null) {
                    appContext.getCurrentPresentation().getCurrentSlide().removeElement(selectedElement);
                }
                redraw();
            }
        }
    }

    public void paste() {
        SlideElement clipboard = appContext.getClipboard();
        if (clipboard != null) {
            SlideElement newElement = clipboard.clone();
            newElement.move(10, 10);
            appContext.getCurrentPresentation().getCurrentSlide().addElement(newElement);
            redraw();
        }
    }

    public void deleteSelectedElement() {
        if (selectedElement != null) {
            appContext.getCurrentPresentation().getCurrentSlide().removeElement(selectedElement);
            if (selectedElement != null) {
                appContext.getCurrentPresentation().getCurrentSlide().removeElement(selectedElement);
            }
            selectedElement = null;
            clearSelection();
            redraw();
        }
    }
}